﻿/* HEADER
 * ------
 * © 2009 by Salomon Zwecker 
 * modified by:
 * - 
 */
using System;
using Microsoft.Xna.Framework;

namespace Shapes.Geometry
{
    /// <summary>
    /// A SplinePoint is a structure to define a point of a B-Spline
    /// </summary>
    public struct SplinePoint : IEquatable<SplinePoint>
    {
        /// <summary>
        /// The Position of the Point
        /// </summary>
        public Vector2 Position;

        /// <summary>
        /// Defines if the Point is a handler to control the curve (true) or if it is a fixed point inside the spline (false)
        /// </summary>
        public bool IsHandler;

       
        /// <summary>
        /// Creates a new SplinePoint
        /// </summary>
        /// <param name="position">the position</param>
        /// <param name="isHandler">handler point (true) or fixed point (false)</param>
        public SplinePoint(Vector2 position, bool isHandler)
        {
            Position = position;
            IsHandler = isHandler;
        }

        /// <summary>
        /// Creates a new SplinePoint
        /// </summary>
        /// <param name="x">the X-coordinate of the point</param>
        /// <param name="y">the Y-coordinate of the point</param>
        /// <param name="isCorner">corner point (true) or handler point (false)</param>
        public SplinePoint(float x, float y, bool isCorner)
        {
            Position = new Vector2(x, y);
            IsHandler = isCorner;
        }


        /// <summary>
        /// checks wether this point is equal to another point
        /// </summary>
        /// <param name="other">the point to compare with</param>
        /// <returns>true, if the points are the same</returns>
        public bool Equals(SplinePoint other)
        {
            return (Position == other.Position) && (IsHandler == other.IsHandler);
        }

        /// <summary>
        /// checks wether this point is equal to another object
        /// </summary>
        /// <param name="obj">the other object</param>
        /// <returns>true, if obj is a SplinePoint with the same values</returns>
        public override bool Equals(object obj)
        {
            if (obj is SplinePoint)
                return Equals((SplinePoint)obj);

            return false;
        }


        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            return (Position.GetHashCode() ^ IsHandler.GetHashCode());
        }

        #region Operators
        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(SplinePoint value1, SplinePoint value2)
        {
            return value1.Equals(value2);
        }
        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(SplinePoint value1, SplinePoint value2)
        {
            return !value1.Equals(value2);
        }
        /// <summary>
        /// Implements the operator -.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator -(SplinePoint value)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = -value.Position.X;
            point.Position.Y = -value.Position.Y;
            point.IsHandler = value.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator +.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator +(SplinePoint value1, SplinePoint value2)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.Position.X + value2.Position.X;
            point.Position.Y = value1.Position.Y + value2.Position.Y;
            point.IsHandler = value1.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator +.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator +(SplinePoint value1, Vector2 value2)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.Position.X + value2.X;
            point.Position.Y = value1.Position.Y + value2.Y;
            point.IsHandler = value1.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator +.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator +(Vector2 value1, SplinePoint value2)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.X + value2.Position.X;
            point.Position.Y = value1.Y + value2.Position.Y;
            point.IsHandler = value2.IsHandler;
            return point;
        }

        /// <summary>
        /// Implements the operator -.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator -(SplinePoint value1, SplinePoint value2)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.Position.X - value2.Position.X;
            point.Position.Y = value1.Position.Y - value2.Position.Y;
            point.IsHandler = value1.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator -.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator -(SplinePoint value1, Vector2 value2)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.Position.X - value2.X;
            point.Position.Y = value1.Position.Y - value2.Y;
            point.IsHandler = value1.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator -.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator -(Vector2 value1, SplinePoint value2)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.X - value2.Position.X;
            point.Position.Y = value1.Y - value2.Position.Y;
            point.IsHandler = value2.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator *.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator *(SplinePoint value1, SplinePoint value2)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.Position.X * value2.Position.X;
            point.Position.Y = value1.Position.Y * value2.Position.Y;
            point.IsHandler = value1.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator *.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator *(SplinePoint value1, Vector2 value2)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.Position.X * value2.X;
            point.Position.Y = value1.Position.Y * value2.Y;
            point.IsHandler = value1.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator *.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator *(Vector2 value1, SplinePoint value2)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.X * value2.Position.X;
            point.Position.Y = value1.Y * value2.Position.Y;
            point.IsHandler = value2.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator *.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="scaleFactor">The scale factor.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator *(SplinePoint value1, float scaleFactor)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.Position.X * scaleFactor;
            point.Position.Y = value1.Position.Y * scaleFactor;
            point.IsHandler = value1.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator *.
        /// </summary>
        /// <param name="scaleFactor">The scale factor.</param>
        /// <param name="value1">The value1.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator *(float scaleFactor, SplinePoint value1)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.Position.X * scaleFactor;
            point.Position.Y = value1.Position.Y * scaleFactor;
            point.IsHandler = value1.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator /.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="divisor">The divisor.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator /(SplinePoint value1, SplinePoint divisor)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.Position.X / divisor.Position.X;
            point.Position.Y = value1.Position.Y / divisor.Position.Y;
            point.IsHandler = value1.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator /.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="divisor">The divisor.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator /(SplinePoint value1, Vector2 divisor)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.Position.X / divisor.X;
            point.Position.Y = value1.Position.Y / divisor.Y;
            point.IsHandler = value1.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator /.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="divisor">The divisor.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator /(Vector2 value1, SplinePoint divisor)
        {
            SplinePoint point = new SplinePoint();
            point.Position.X = value1.X / divisor.Position.X;
            point.Position.Y = value1.Y / divisor.Position.Y;
            point.IsHandler = divisor.IsHandler;
            return point;
        }
        /// <summary>
        /// Implements the operator /.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="divisor">The divisor.</param>
        /// <returns>The result of the operator.</returns>
        public static SplinePoint operator /(SplinePoint value1, float divisor)
        {
            SplinePoint point = new SplinePoint();
            float multiply = 1 / divisor;
            point.Position.X = value1.Position.X * divisor;
            point.Position.Y = value1.Position.Y * divisor;
            point.IsHandler = value1.IsHandler;
            return point;
        }
        #endregion
    }
}